package com.sdhs.myproject.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.gson.JsonObject;
import com.sdhs.common.utils.*;
import com.sdhs.projectstart.domain.ProjectDept;
import com.sdhs.projectstart.mapper.ProjectDeptMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sdhs.util.SafetyProjectUnit;
import com.sdhs.common.annotation.DataScope;
import com.sdhs.myproject.domain.GcMyprojectAssociatedUnit;
import com.sdhs.myproject.domain.GcMyprojectContractInformation;
import com.sdhs.myproject.domain.GcMyprojectInformation;
import com.sdhs.myproject.domain.GcMyprojectProfitMarginMeasurement;
import com.sdhs.myproject.domain.ProjectManageCost;
import com.sdhs.myproject.mapper.GcMyprojectAssociatedUnitMapper;
import com.sdhs.myproject.mapper.GcMyprojectContractInformationMapper;
import com.sdhs.myproject.mapper.GcMyprojectInformationMapper;
import com.sdhs.myproject.mapper.GcMyprojectProfitMarginMeasurementMapper;
import com.sdhs.myproject.service.IGcMyprojectInformationService;
import com.sdhs.myproject.service.IProjectManageCostService;
import com.sdhs.projectschedule.mapper.GcProgressPaymentCollectionTrackingMapper;
import com.sdhs.qualitymanage.domain.GcQuality;
import com.sdhs.qualitymanage.domain.GcQualityManagement;
import com.sdhs.qualitymanage.mapper.GcQualityManagementMapper;
import com.sdhs.qualitymanage.mapper.GcQualityMapper;
import com.sdhs.system.domain.GcContract;
import com.sdhs.system.domain.GcContractParty;
import com.sdhs.system.mapper.GcContractMapper;
import com.sdhs.system.service.ISysDeptService;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;

/**
 * 我的项目--项目基本信息Service业务层处理
 *
 * @author andong
 * @date 2025-03-11
 */
@Service
public class GcMyprojectInformationServiceImpl implements IGcMyprojectInformationService
{
    @Autowired
    private GcMyprojectInformationMapper gcMyprojectInformationMapper;

    @Autowired
    private GcMyprojectAssociatedUnitMapper gcMyprojectAssociatedUnitMapper;

    @Autowired
    private GcMyprojectContractInformationMapper gcMyprojectContractInformationMapper;

    @Autowired
    private GcMyprojectProfitMarginMeasurementMapper gcMyprojectProfitMarginMeasurementMapper;

    @Autowired
    private GcQualityMapper gcQualityMapper;

    @Autowired
    private GcQualityManagementMapper gcQualityManagementMapper;
    @Autowired
    private GcContractMapper gcContractMapper;
    @Autowired
    private GcProgressPaymentCollectionTrackingMapper gcProgressPaymentCollectionTrackingMapper;
    @Autowired
    private ISysDeptService iSysDeptService;
    
    @Autowired
    private IProjectManageCostService projectManageCostService;
    @Autowired
    private ProjectDeptMapper projectDeptMapper;
    
    /**
     * 根据项目id查询项目关联的供应商列表
     * @param id
     * @return
     */
    @Override
    public List<GcContractParty> selectSupplierByProjectId(Long id)
    {
    	List<GcContractParty> list = gcMyprojectContractInformationMapper.selectSupplierByProjectId(id);
    	return list;
    }

    /**
     * 根据项目id查询项目关联的合同列表
     * @param id
     * @return
     */
    @Override
    public List<GcMyprojectContractInformation> selectContractByProjectId(Long id)
    {
    	List<GcMyprojectContractInformation> list = gcMyprojectContractInformationMapper.selectGcMyprojectContractByIdList(id);
    	return list;
    }
    @Override
    public GcMyprojectInformation selectProjectInformationByNumber(String projectNumber)
    {
        return  gcMyprojectInformationMapper.selectProjectInformationByNumber(projectNumber);
    }
    /**
     * 查询我的项目--项目基本信息
     *
     * @param id 我的项目--项目基本信息主键
     * @return 我的项目--项目基本信息
     */
    @Override
    public GcMyprojectInformation selectGcMyprojectInformationById(Long id)
    {
        GcMyprojectInformation gcMyprojectInformation = gcMyprojectInformationMapper.selectGcMyprojectInformationById(id);
        if(gcMyprojectInformation != null){
            //项目关联单位
            GcMyprojectAssociatedUnit gcMyprojectAssociatedUnit = gcMyprojectAssociatedUnitMapper.selectGcMyprojectAssociatedUnitById(id);
            gcMyprojectInformation.setGcMyprojectAssociatedUnit(gcMyprojectAssociatedUnit);
            // 项目管理费用明细
            ProjectManageCost projectManageCost = projectManageCostService.getByProjectId(id);
            gcMyprojectInformation.setProjectManageCost(projectManageCost);
            //项目合同信息对象
            List<GcMyprojectContractInformation> gcMyprojectContractInformation = gcMyprojectContractInformationMapper.selectGcContractByIdList(id, "收入类");
            if (gcMyprojectContractInformation != null && !gcMyprojectContractInformation.isEmpty()) {
                // 2. 收集所有主合同的编号（用于批量查询子合同）
                List<String> mainContractNums = gcMyprojectContractInformation.stream()
                        .map(GcMyprojectContractInformation::getNum)
                        .toList();
                // 3. 批量查询所有子合同（IsSupplementaryContract = "1" 且 OriginalContractNum 在 mainContractNums 中）
                GcContract queryParam = new GcContract();
                queryParam.setIsSupplementaryContract("1");
                queryParam.setOriginalContractNums(mainContractNums); // 假设 Mapper 支持批量查询
                List<GcContract> supplementaryContracts = gcContractMapper.selectGcContractList(queryParam);
                // 将合同数据转为我的合同数据
                List<GcMyprojectContractInformation> supplementaryInfoList = supplementaryContracts.stream()
                        .map(suppContract -> {
                            GcMyprojectContractInformation info = new GcMyprojectContractInformation();
                            BeanUtils.copyProperties(suppContract, info);
                            return info;
                        })
                        .toList();

                // 按 OriginalContractNum 分组（Key=主合同Num，Value=对应的子合同列表）
                Map<String, List<GcMyprojectContractInformation>> supplementaryMap = supplementaryInfoList.stream()
                        .collect(Collectors.groupingBy(GcMyprojectContractInformation::getOriginalContractNum));

                // 遍历主合同，设置 money 和子合同
                for (GcMyprojectContractInformation mainContract : gcMyprojectContractInformation) {


                    // 获取子合同列表
                    List<GcMyprojectContractInformation> children = supplementaryMap.getOrDefault(mainContract.getNum(), Collections.emptyList());
                    mainContract.setChildren(children);
                    // 遍历子合同，如果 contractMoney 有值，且子合同不为空 则赋值给子合同 money
                    if (mainContract.getContractMoney() != null && children.size()>0) {
                        for (GcMyprojectContractInformation child : children) {
                            if (mainContract.getContractMoney() != null) {
                                child.setMoney(mainContract.getContractMoney());
                            }
                        }
                        // 如果 contractMoney 有值，且子合同为空 则赋值给主合同 money
                    }else if (mainContract.getContractMoney() != null && children.size()==0){
                        mainContract.setMoney(mainContract.getContractMoney());
                    }
                }

                // 标记已删除的合同
                gcMyprojectContractInformation.forEach(contract -> {
                    if ("1".equals(contract.getIsDelete())) {
                        contract.setName(contract.getName() + "(已解除)");
                    }
                });

                gcMyprojectInformation.setGcMyprojectContractInformationList(gcMyprojectContractInformation);
            }

            // 利润率测算对象
            GcMyprojectProfitMarginMeasurement gcMyprojectProfitMarginMeasurement = gcMyprojectProfitMarginMeasurementMapper.selectGcMyprojectProfitMarginMeasurementById(id);

            if (gcMyprojectProfitMarginMeasurement != null) {
                String handover = gcMyprojectProfitMarginMeasurement.getHandoverUtilization();
                String completion = gcMyprojectProfitMarginMeasurement.getCompletionUtilization();

                // 如果两个都有值（非null），优先取 completion
                // 否则，取任意一个有值的（handover 或 completion）
                String implementValue;

                if (StringUtils.isNotEmpty(handover) && StringUtils.isNotEmpty(completion)) {
                    implementValue = completion;
                } else if (StringUtils.isNotEmpty(handover) && StringUtils.isEmpty(completion)) {
                    implementValue = handover;
                } else if (StringUtils.isNotEmpty(completion) && StringUtils.isEmpty(handover)) {
                    implementValue = completion;
                }else {
                    implementValue = gcMyprojectProfitMarginMeasurement.getImplementUtilization();
                }

                // 确保 implementValue 不是空字符串（如果需要）
                    gcMyprojectProfitMarginMeasurement.setImplementUtilization(implementValue);
            }
            gcMyprojectInformation.setGcMyprojectProfitMarginMeasurement(gcMyprojectProfitMarginMeasurement);
            /*查询项目部组建信息*/
             ProjectDept projectDept = projectDeptMapper.selectDeptProjectId(id);
             if (projectDept != null){
                 gcMyprojectInformation.setManagerName(projectDept.getManagerName());
             }

        }
        return gcMyprojectInformation;
    }

    /**
     * 查询我的项目--项目基本信息列表
     *
     * @param gcMyprojectInformation 我的项目--项目基本信息
     * @return 我的项目--项目基本信息
     */
    @Override
    @DataScope(companyAlias = "p.organization", deptAlias = "d", userAlias = "u.user_name_arr", createByAlias = "p.creater")
    public List<GcMyprojectInformation> selectGcMyprojectInformationList(GcMyprojectInformation gcMyprojectInformation)
    {
        PageUtils.startPage();
        return gcMyprojectInformationMapper.selectGcMyprojectInformationList(gcMyprojectInformation);
    }

    @Override
    @DataScope(companyAlias = "p.organization", deptAlias = "d", userAlias = "u.user_name_arr", createByAlias = "p.creater")
    public List<GcMyprojectInformation> selectAllProjectInformationList(GcMyprojectInformation gcMyprojectInformation) {
        return gcMyprojectInformationMapper.selectGcMyprojectInformationList(gcMyprojectInformation);
    }

    @Override
    public List<GcMyprojectInformation> selectMyprojectList(GcMyprojectInformation gcMyprojectInformation)
    {
        return gcMyprojectInformationMapper.selectMyprojectList(gcMyprojectInformation);
    }
    /**
     * 查询--汇款填报总金额 -- 管理成本维护总金额 --合同支付跟踪总金额
     *  用于计算项目实施期利润率
     * @param id 我的项目--项目基本信息主键
     * @return 我的项目--项目基本信息
     */
    @Override
    public GcMyprojectInformation selectImplementUtilizationById(Long id)
    {
        return gcMyprojectInformationMapper.selectImplementUtilizationById(id);
    }
    /**
     * 查询我的项目--项目id以及项目经理id
     *
     * @param id 我的项目--项目基本信息主键
     */
    @Override
    public GcMyprojectInformation selectGcMyProjectInformationByProject(Long id)
    {
        return gcMyprojectInformationMapper.selectGcMyProjectInformationByProject(id);
    }
    /**
     * 查询我的项目--项目id以及项目经理id
     *
     * @param id 我的项目--项目基本信息主键
     */
    @Override
    public GcMyprojectInformation selectDeptByProject(Long id)
    {
        return gcMyprojectInformationMapper.selectDeptByProject(id);
    }

    /**
     * 新增我的项目--项目基本信息
     *
     * @param gcMyprojectInformation 我的项目--项目基本信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertGcMyprojectInformation(GcMyprojectInformation gcMyprojectInformation)
    {
       // GcMyprojectInformation add = BeanUtil.toBean(gcMyprojectInformation, GcMyprojectInformation.class);
       /* 营销的创建人是"用户名（协办单位项目负责人），如果是营销的话就不改用户名，如果不是就取当前用户名"*/
        if (gcMyprojectInformation.getCreater()== null){
            gcMyprojectInformation.setCreater(SecurityUtils.getUsername());
        }


        GcMyprojectInformation gcInformation = gcMyprojectInformationMapper.selectDeptByName(gcMyprojectInformation.getCreater());
        gcMyprojectInformation.setDeptId(gcInformation.getDeptId());

        gcMyprojectInformation.setCreateTime(DateUtils.getNowDate());

        /*给安全项目推送项目并返回安全的id*/
        Long safetyId = SafetyProjectUnit.addSafetyProject(gcMyprojectInformation);
        gcMyprojectInformation.setSafetyProjectId(safetyId);
        int i = gcMyprojectInformationMapper.insertGcMyprojectInformation(gcMyprojectInformation);
        handler(gcMyprojectInformation.getId(),gcMyprojectInformation);
        safetyHandler(gcMyprojectInformation,"add");
        /*推送安全项目结束*/
        /*查询质量管理默认清单list*/
        List<GcQuality> gcQualities = gcQualityMapper.selectGcQualityEmptyList();
        /*给质量管理一个默认的list*/
        for (GcQuality gcQuality : gcQualities) {
            GcQualityManagement gcAdd = BeanUtil.toBean(gcQuality, GcQualityManagement.class);
            gcAdd.setProjectId(gcMyprojectInformation.getId());
            gcQualityManagementMapper.insertGcQualityManagement(gcAdd);
        }
        return i;
    }

    /**
     * 修改我的项目--项目基本信息
     *
     * @param gcMyprojectInformation 我的项目--项目基本信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateGcMyprojectInformation(GcMyprojectInformation gcMyprojectInformation)
    {
        gcMyprojectInformation.setUpdater(SecurityUtils.getUsername());
        gcMyprojectInformation.setUpdateTime(DateUtils.getNowDate());
        int i = gcMyprojectInformationMapper.updateGcMyprojectInformation(gcMyprojectInformation);
        handler(gcMyprojectInformation.getId(),gcMyprojectInformation);
        safetyHandler(gcMyprojectInformation,"update");
        List<GcQualityManagement> gcQualityManagements = gcQualityManagementMapper.selectGcQualityManagementByProjectIdList(gcMyprojectInformation.getId());
       /* 如果是营销项目的话走修改的时候给质量管理一个默认的清单管理*/
        if (null == gcQualityManagements){
            /*查询质量管理默认清单list*/
            List<GcQuality> gcQualities = gcQualityMapper.selectGcQualityEmptyList();
            /*给质量管理一个默认的list*/
            for (GcQuality gcQuality : gcQualities) {
                GcQualityManagement gcAdd = BeanUtil.toBean(gcQuality, GcQualityManagement.class);
                gcAdd.setProjectId(gcMyprojectInformation.getId());
                gcQualityManagementMapper.insertGcQualityManagement(gcAdd);
            }
        }
        return i;
    }
    /**
     * 推送安全项目
     */

    @Transactional(rollbackFor = Exception.class)
    public void safetyHandler( GcMyprojectInformation gcMyprojectInformation,String type) {
        /*修改推送安全项目开始*/
        if (gcMyprojectInformation.getId()!=null){
            JsonObject jsonObject = new JsonObject();
            jsonObject.addProperty("engineeringId", gcMyprojectInformation.getId()); //项目id
            jsonObject.addProperty("type", type); //类型
            jsonObject.addProperty("status", "2"); //项目状态-实施中
            jsonObject.addProperty("companyId", gcMyprojectInformation.getOrganization()); //项目所属公司
            jsonObject.addProperty("no", gcMyprojectInformation.getProjectNumber()); //项目编号
            jsonObject.addProperty("name", gcMyprojectInformation.getProjectName()); //项目名称
            jsonObject.addProperty("shortName", gcMyprojectInformation.getProjectName()); //项目简称
            jsonObject.addProperty("startDate", gcMyprojectInformation.getPlanStartTime().toString()); //项目开始时间
            jsonObject.addProperty("endDate", gcMyprojectInformation.getPlanEndTime().toString());//项目结束时间
            jsonObject.addProperty("createBy", gcMyprojectInformation.getCreater());//创建人
            jsonObject.addProperty("createTime", gcMyprojectInformation.getCreateTime().toString());//创建时间
            try {
                String jsonData = jsonObject.toString(); // 直接转为JSON字符串
                String encryptedData = AESUtils.encrypt(jsonData);
                /*推送安全接口*/
                SafetyUtil.pushUrl(encryptedData);
            } catch (JsonProcessingException e) {
                System.err.println("JSON序列化失败: " + e.getMessage());
                throw new RuntimeException(e);
            } catch (Exception e) {
                System.err.println("加密失败: " + e.getMessage());
                throw new RuntimeException(e);
            }
        }
        /*推送安全项目结束*/
    }
    /**
     * 设置项目--项目状态为督办
     *
     * @param gcMyprojectInformation 设置项目--项目状态为督办
     * @return 结果
     */
    @Override
    public int markSupervise(GcMyprojectInformation gcMyprojectInformation) {
        return gcMyprojectInformationMapper.markSupervise(gcMyprojectInformation);
    }

    /**
     * 项目交工，竣工，项目部组建修改项目状态
     * */
    public int updateGcMyProject(GcMyprojectInformation gcMyprojectInformation){
        return gcMyprojectInformationMapper.updateGcMyProject(gcMyprojectInformation);
    }
    /**
     * 批量删除我的项目--项目基本信息
     *
     * @param ids 需要删除的我的项目--项目基本信息主键
     * @return 结果
     */
    @Override
    public int deleteGcMyprojectInformationByIds(Long[] ids)
    {
        return gcMyprojectInformationMapper.deleteGcMyprojectInformationByIds(ids);
    }

    /**
     * 删除我的项目--项目基本信息信息
     *
     * @param id 我的项目--项目基本信息主键
     * @return 结果
     */
    @Override
    public int deleteGcMyprojectInformationById(Long id)
    {
        return gcMyprojectInformationMapper.deleteGcMyprojectInformationById(id);
    }



    /**
     * 保存数据

     * 1-项目关联单位
     * 2-合同信息
     * 3-利润率测算
     */
    public void handler(Long id, GcMyprojectInformation gcMyprojectInformation) {

        //项目关联单位
        GcMyprojectAssociatedUnit gcMyprojectAssociatedUnit = gcMyprojectInformation.getGcMyprojectAssociatedUnit();
        if (gcMyprojectAssociatedUnit!=null){
            gcMyprojectAssociatedUnit.setProjectId(id);
            GcMyprojectAssociatedUnit gcMyprojectUnit = gcMyprojectAssociatedUnitMapper.selectGcMyprojectAssociatedUnitById(id);
            if (gcMyprojectUnit!=null){
                gcMyprojectAssociatedUnitMapper.deleteGcMyprojectAssociatedUnitById(id);
            }
            gcMyprojectAssociatedUnitMapper.insertGcMyprojectAssociatedUnit(gcMyprojectAssociatedUnit);
        }

        //利润率测算
        GcMyprojectProfitMarginMeasurement gcMyprojectProfitMarginMeasurement = gcMyprojectInformation.getGcMyprojectProfitMarginMeasurement();
        if (gcMyprojectProfitMarginMeasurement!=null){
            gcMyprojectProfitMarginMeasurement.setProjectId(id);
            GcMyprojectProfitMarginMeasurement gcMyprojectMeasurement = gcMyprojectProfitMarginMeasurementMapper.selectGcMyprojectProfitMarginMeasurementById(id);
            if (gcMyprojectMeasurement!=null){
                gcMyprojectProfitMarginMeasurementMapper.deleteGcMyprojectProfitMarginMeasurementById(id);
            }
            gcMyprojectProfitMarginMeasurementMapper.insertGcMyprojectProfitMarginMeasurement(gcMyprojectProfitMarginMeasurement);
        }
        
        // 项目管理费用明细
        ProjectManageCost projectManageCost = gcMyprojectInformation.getProjectManageCost();
        if (projectManageCost != null) {
        	projectManageCost.setProjectId(id);
        	projectManageCostService.saveOrUpdate(projectManageCost);
        }
        
        //合同信息
        List<GcMyprojectContractInformation> gcMyprojectContractInformationList = gcMyprojectInformation.getGcMyprojectContractInformationList();
        //如果合同不为空的时候删除之前的数据,即修改的时候先删除再新增
        if (CollectionUtil.isNotEmpty(gcMyprojectContractInformationList)){
            // 只删除【收入类】合同
            List<GcMyprojectContractInformation> contractInfoList = gcMyprojectContractInformationMapper.selectGcContractByIdList(id, "收入类");
            if(contractInfoList != null && !contractInfoList.isEmpty()){
                List<String> contractInfoIdList = new ArrayList<>();
                contractInfoList.forEach(contractInfo -> {
                    contractInfoIdList.add(contractInfo.getContractId());
                });
                gcMyprojectContractInformationMapper.deleteGcMyprojectContractInformationById(id, contractInfoIdList);
            }
            // 2. 收集所有主合同的编号（用于批量查询子合同）
            List<String> mainContractNums = gcMyprojectContractInformationList.stream()
                    .map(GcMyprojectContractInformation::getNum)
                    .toList();
            // 3. 批量查询所有子合同（IsSupplementaryContract = "1" 且 OriginalContractNum 在 mainContractNums 中）
            GcContract queryParam = new GcContract();
            queryParam.setIsSupplementaryContract("1");
            queryParam.setOriginalContractNums(mainContractNums); //  Mapper 支持批量查询
            List<GcContract> supplementaryContracts = gcContractMapper.selectGcContractList(queryParam);
            // 将合同数据转为我的合同数据
            List<GcMyprojectContractInformation> supplementaryInfoList = supplementaryContracts.stream()
                    .map(suppContract -> {
                        GcMyprojectContractInformation info = new GcMyprojectContractInformation();
                        BeanUtils.copyProperties(suppContract, info);
                        return info;
                    })
                    .toList();

            // 按 OriginalContractNum 分组（Key=主合同Num，Value=对应的子合同列表）
            Map<String, List<GcMyprojectContractInformation>> supplementaryMap = supplementaryInfoList.stream()
                    .collect(Collectors.groupingBy(GcMyprojectContractInformation::getOriginalContractNum));

            for (int i = 0;i<gcMyprojectContractInformationList.size();i++){
                // 获取子合同列表
                List<GcMyprojectContractInformation> children = supplementaryMap.getOrDefault(gcMyprojectContractInformationList.get(i).getNum(), Collections.emptyList());
                /*将子合同列表赋值给当前子合同*/
                gcMyprojectContractInformationList.get(i).setChildren(children);

                GcMyprojectContractInformation gcMyprojectContractInformation = gcMyprojectContractInformationList.get(i);
                BigDecimal money = gcMyprojectContractInformation.getMoney();
                String contractId = gcMyprojectContractInformation.getContractId();
                /*根据合同id查询合同信息*/
                GcContract gcContract = gcContractMapper.selectGcContractByContractId(contractId);
                BigDecimal money1 = gcContract.getMoney();
                /*如果没有子合同的话比较合同金额和传过来的金额是否一致*/
                if(StringUtils.isEmpty(gcMyprojectContractInformationList.get(i).getChildren())){

                    /*如果输入的合同金额和实际合同金额一致的时候，则将我的项目的合同信息的合同金额置为空否则就将合同信息设置为输入的合同金额*/
                    if (money.compareTo(money1) == 0) {
                        gcMyprojectContractInformation.setContractMoney(null);
                    } else {
                        gcMyprojectContractInformation.setContractMoney(money);
                    }
                    /*如果有子合同的话比较子合同金额和传过来的金额是否一致*/
                }else{
                     BigDecimal money2 = gcMyprojectContractInformationList.get(i).getChildren().get(0).getMoney();
                    if (money2.compareTo(money) == 0) {
                        gcMyprojectContractInformation.setContractMoney(null);
                    } else {
                        gcMyprojectContractInformation.setContractMoney(money);
                    }
                }

                gcMyprojectContractInformation.setProjectId(id);
                gcMyprojectContractInformation.setId(null);
                gcMyprojectContractInformationMapper.insertGcMyprojectContractInformation(gcMyprojectContractInformation);
            }
        }
    }
}
